<script setup lang="ts">
import { ref } from 'vue';

import { useVbenModal, z } from '@vben/common-ui';

import { message } from 'ant-design-vue';

import { useVbenForm } from '#/adapter/form';
import { querySelectTableApi, querySelectTreeTableApi } from '#/api';
import {
  sysUserAddApi,
  sysUserEditApi,
  sysUserQueryByIdApi,
} from '#/api/system/sysUser';
import { queryDictOptionsApi } from '#/utils';
import { asyncValidDataApi } from '#/utils/handle/async-rules';

const record = ref({});
const [Form, formApi] = useVbenForm({
  layout: 'horizontal',
  wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-2',
  showDefaultActions: false,
  commonConfig: {
    colon: true,
    labelWidth: 80,
    componentProps: {
      class: 'w-full',
    },
  },
  schema: [
    {
      component: 'SparkUpload',
      label: '头像',
      fieldName: 'avatar',
      formItemClass: 'col-span-2',
      componentProps: {
        maxCount: 1,
      },
    },
    {
      component: 'Input',
      label: '用户昵称',
      fieldName: 'nickname',
      componentProps: {
        placeholder: '请输入用户昵称',
      },
      rules: z.string().max(15, '昵称最多15个字符').optional(),
    },
    {
      component: 'Input',
      label: '用户账号',
      fieldName: 'username',
      componentProps: {
        placeholder: '请输入用户账号',
      },
      dependencies: {
        // 实现异步API校验
        rules(values, formApi) {
          const rowId = formApi.values?.id;
          return asyncValidDataApi(
            z
              .string({ required_error: '请输入用户账号' })
              .trim()
              .min(3, '用户账号至少3个字符')
              .max(30, '用户账号最多30个字符')
              .refine((val) => !val || /^[a-z0-9]*$/i.test(val), {
                message: '用户账号只能包含字母或数字',
              }),
            {
              tableName: 'sys_user',
              fieldName: 'username',
              rowId,
            },
          );
        },
        triggerFields: ['username'],
      },
    },
    {
      component: 'InputPassword',
      label: '用户密码',
      fieldName: 'password',
      componentProps: {
        placeholder: '请输入用户密码',
      },
      dependencies: {
        show(values) {
          return !values.id;
        },
        triggerFields: ['id'],
      },
      rules: z
        .string()
        .min(6, '用户密码至少6个字符')
        .max(18, '用户密码最多18个字符')
        .refine((val) => /^(?=.*[a-z])(?=.*\d)[a-z\d!@#$%.,;]+$/i.test(val), {
          message: '密码必须包含一个字母和一个数字特殊符号：!@#$%.,;',
        }),
    },
    {
      component: 'Input',
      label: '邮箱',
      fieldName: 'email',
      componentProps: {
        placeholder: '请输入邮箱',
      },
      rules: z.string().trim().email('请输入正确的邮箱').nullish(),
    },
    {
      component: 'Input',
      label: '手机号',
      fieldName: 'phone',
      componentProps: {
        placeholder: '请输入手机号',
      },
      rules: z
        .string()
        .regex(/^1[3-9]\d{9}$/, {
          message: '请输入有效的手机号',
        })
        .nullish(),
    },
    {
      component: 'ApiSelect',
      componentProps: {
        api: querySelectTableApi,
        params: {
          tableName: 'sys_role',
          labelField: 'role_name',
          valueField: 'id',
          sqlSelect: 'del_flag = 0',
        },
        mode: 'multiple',
        allowClear: true,
      },
      fieldName: 'roleIds',
      label: '用户角色',
    },
    {
      component: 'ApiTreeSelect',
      label: '部门',
      fieldName: 'deptId',
      componentProps: {
        placeholder: '请选择部门',
        api: () =>
          querySelectTreeTableApi({
            tableName: 'sys_dept',
            labelField: 'dept_name',
            valueField: 'id',
            sqlSelect: 'del_flag = 0',
          }),
        labelField: 'name',
        childrenField: 'children',
        valueField: 'id',
      },
    },
    {
      component: 'ApiRadioGroup',
      label: '性别',
      fieldName: 'sex',
      defaultValue: 2,
      componentProps: {
        buttonStyle: 'solid',
        optionType: 'button',
        afterFetch: (data) => {
          return data.map((item: any) => ({
            label: item.itemText,
            value: Number.parseInt(item.itemVal),
          }));
        },
        api: queryDictOptionsApi,
        params: {
          dictCode: 'sex',
        },
      },
    },
    {
      component: 'ApiRadioGroup',
      label: '状态',
      fieldName: 'status',
      defaultValue: 0,
      componentProps: {
        buttonStyle: 'solid',
        optionType: 'button',
        afterFetch: (data) => {
          return data.map((item: any) => ({
            label: item.itemText,
            value: Number.parseInt(item.itemVal),
          }));
        },
        api: queryDictOptionsApi,
        params: {
          dictCode: 'status',
        },
      },
    },
    {
      component: 'Textarea',
      label: '备注',
      fieldName: 'remark',
      formItemClass: 'col-span-2',
      componentProps: {
        placeholder: '请输入备注',
      },
    },
  ],
});

const [Modal, modalApi] = useVbenModal({
  title: 'Modal',
  onCancel: () => {
    modalApi.close();
  },
  onConfirm: onSubmit,
  onOpenChange(isOpen: boolean) {
    if (isOpen) {
      record.value = modalApi.getData<Record<string, any>>();
      modalApi.setState({
        title: `${record.value.id ? '编辑' : '新增'}系统用户`,
      });
      if (record.value.id) {
        initFun();
      }
    }
  },
});

async function initFun() {
  const res = await sysUserQueryByIdApi({ id: record.value.id });
  res.roleIds = res.roleIds ? res.roleIds.split(',') : [];
  await formApi.setValues(res, false);
}
async function onSubmit() {
  const { valid } = await formApi.validate();
  const values = await formApi.getValues();
  if (valid) {
    const updatedValues = { ...values };
    if (updatedValues.roleIds) {
      updatedValues.roleIds = updatedValues.roleIds.join(',');
    }
    if (record.value.id) {
      const msg = await sysUserEditApi(updatedValues);
      message.success(msg);
      await modalApi.close();
    } else {
      const msg = await sysUserAddApi(updatedValues);
      message.success(msg);
      await modalApi.close();
    }
  }
}
</script>

<template>
  <Modal>
    <Form />
  </Modal>
</template>
